package cn.com.twoke.easyproject.handler;


import cn.com.twoke.easyproject.common.constant.Profile;
import cn.com.twoke.easyproject.common.exception.BusinessException;
import cn.com.twoke.easyproject.common.response.BusinessCode;
import cn.com.twoke.easyproject.common.response.R;
import cn.com.twoke.easyproject.common.response.ResponseCode;
import cn.com.twoke.easyproject.common.response.Result;
import cn.com.twoke.easyproject.config.spi.GlobalErrorMessageHandler;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 全局统一异常处理
 */
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler {

    private final GlobalErrorMessageHandler messageHandler;

    /**
     * 业务异常统一处理
     * @param e
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Result<Object>> businessException(BusinessException e) {
        log.error(BusinessCode.ERROR.message, e);
        return wrapperErrorResult(null, HttpStatus.OK.value(),  e.getCode(), e.getMessage(),  e.getMessage());
    }

    /**
     * 资源未找到处理
     * @param e
     * @return
     */
    @ExceptionHandler({NotFoundException.class, NoHandlerFoundException.class})
    public ResponseEntity<Result<Object>> businessException(Throwable e) {
        log.error(ResponseCode.NOT_FOUND.message, e);
        return wrapperErrorResult(ResponseCode.NOT_FOUND,  e.getMessage());
    }

    /**
     * 登录校验
     * @param e
     * @return
     */
    @ExceptionHandler(value = {NotLoginException.class})
    public ResponseEntity<Result<Object>> notLoginExceptionHandler(NotLoginException e) {
        log.error(ResponseCode.UNAUTHORIZED.message, e);
        return wrapperErrorResult(ResponseCode.UNAUTHORIZED,  e.getMessage());
    }

    /**
     * 参数校验异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class})
    public ResponseEntity<Result<Object>> bindExceptionHandler(Exception e) {
        BindingResult bindingResult = null;
        if (e instanceof MethodArgumentNotValidException) {
            bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
        } else if (e instanceof BindException) {
            bindingResult = ((BindException) e).getBindingResult();
        }
        List<String> list = new CopyOnWriteArrayList<>();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            log.error("客户端参数校验错误：{} - {}", fieldError.getField(), fieldError.getDefaultMessage());
            list.add(fieldError.getDefaultMessage());
        }
        Collections.sort(list);
        return wrapperErrorResult(list, ResponseCode.BAD_REQUEST_VALID, list.stream().collect(Collectors.joining(",")));
    }

    /**
     * 参数处理异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {IllegalArgumentException.class, HttpRequestMethodNotSupportedException.class})
    public ResponseEntity<Result<Object>> illegalArgumentExceptionHandler(Throwable e) {
        log.error(ResponseCode.BAD_REQUEST.message, e);
        return wrapperErrorResult(ResponseCode.BAD_REQUEST, e.getMessage());
    }

    /**
     * 服务端未知异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    public ResponseEntity<Result< Object>> exceptionHandler(Throwable e) {
        log.error(ResponseCode.INTERNAL_SERVER_ERROR.message, e);
        return wrapperErrorResult(ResponseCode.INTERNAL_SERVER_ERROR, e.getMessage());
    }

    public  ResponseEntity<Result<Object>> wrapperErrorResult( ResponseCode responseCode, String tips) {
        return wrapperErrorResult(null, responseCode, tips);
    }

    public  ResponseEntity<Result<Object>> wrapperErrorResult(Object data,  ResponseCode responseCode, String tips) {
        return wrapperErrorResult(data, responseCode.code, responseCode.message, tips);
    }

    public  ResponseEntity<Result<Object>> wrapperErrorResult(Object data, Integer code, String message, String tips) {
        return wrapperErrorResult(data, code, code, message, tips);
    }

    public  ResponseEntity<Result<Object>> wrapperErrorResult(Object data,Integer status, Integer code, String message, String tips) {
        return ResponseEntity.status(status).body(messageHandler.handle(data, code, message, tips));
    }


}
